home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvipage / sample.c < prev    next >
C/C++ Source or Header  |  1992-05-11  |  30KB  |  1,246 lines

  1. /*
  2.  * dvipage: DVI Previewer Program for Suns
  3.  *
  4.  * Neil Hunt (hunt@spar.slb.com)
  5.  *
  6.  * This program is based, in part, upon the program dvisun,
  7.  * distributed by the UnixTeX group, extensively modified by
  8.  * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
  9.  * of Schlumberger Technologies, Inc.
  10.  *
  11.  * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
  12.  * Anyone can use this software in any manner they choose,
  13.  * including modification and redistribution, provided they make
  14.  * no charge for it, and these conditions remain unchanged.
  15.  *
  16.  * This program is distributed as is, with all faults (if any), and
  17.  * without any warranty. No author or distributor accepts responsibility
  18.  * to anyone for the consequences of using it, or for whether it serves any
  19.  * particular purpose at all, or any other reason.
  20.  *
  21.  * $Log:    sample.c,v $
  22.  * Revision 1.1  88/11/28  18:41:24  hunt
  23.  * Initial revision
  24.  * 
  25.  * Split out of dvipage.c version 1.4.
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <sys/param.h>        /* For MAXPATHLEN */
  30. #include <suntool/sunview.h>
  31. #include <suntool/canvas.h>
  32. #include "dvipage.h"
  33.  
  34. forward struct pixrect *    pr_alloc();
  35. forward struct pixrect *    pr_free();
  36. forward struct pixrect *    pr_check();
  37. forward struct pixrect *    pr_link();
  38. forward struct pixrect *    pr_sample_4();
  39. forward struct pixrect *    pr_sample_34();
  40. forward struct pixrect *    pr_sample_3();
  41. forward struct pixrect *    pr_sample_2();
  42.  
  43. forward void            pw_cover();
  44. forward void            pr_rect();
  45. forward void            pw_rect();
  46.  
  47. /*
  48.  * sample_page:
  49.  *    Filter and sample down page according to current sampling rate,
  50.  *    and prepare for display.
  51.  */
  52.  
  53. void
  54. sample_page()
  55. {
  56.  
  57. #ifdef TIMING
  58.     start_time();
  59. #endif TIMING
  60.  
  61.     switch(sampling)
  62.     {
  63.     default:
  64.     case 1:
  65.         sample_pr = pr_link(&page_mpr, &sample_mpr);
  66.         break;
  67.  
  68.     case 2:
  69.         if(! (sample_pr = pr_sample_2(&page_mpr, &sample_mpr)))
  70.             message("Out of memory for resampling image");
  71.         break;
  72.  
  73.     case 3:
  74.         if(! (sample_pr = pr_sample_3(&page_mpr, &sample_mpr)))
  75.             message("Out of memory for resampling image");
  76.         break;
  77.  
  78.     case 4:
  79.         if(! (sample_pr = pr_sample_4(&page_mpr, &sample_mpr)))
  80.             message("Out of memory for resampling image");
  81.         break;
  82.  
  83.     case 5:
  84.         if(! (sample_pr = pr_sample_34(&page_mpr, &sample_mpr)))
  85.             message("Out of memory for resampling image");
  86.         break;
  87.     }
  88.  
  89. #ifdef TIMING
  90.     stop_time("Sampling one page");
  91. #endif TIMING
  92.  
  93. }
  94.  
  95. /*
  96.  * Here follow some functions to deal with pixrects under the special case
  97.  * assumption that they are mem_pixrects, where the mpr_data is part
  98.  * of a parent structure.
  99.  */
  100.  
  101. extern struct pixrectops mem_ops;
  102.  
  103. /*
  104.  * pr_alloc:
  105.  *    Allocate memory for a pixrect of size w, h, d.
  106.  *    Returns a pointer to the pixrect structure.
  107.  */
  108.  
  109. struct pixrect *
  110. pr_alloc(mpr, w, h, d)
  111. struct mem_pixrect *mpr;
  112. int w, h, d;
  113. {
  114.     int size;
  115.     int linebytes;
  116.     short *image;
  117.  
  118.     /*
  119.      * Compute the size of memory needed, and alloc it.
  120.      */
  121.     linebytes = mpr_linebytes(w, d);
  122.     size = linebytes * h;
  123.     if(! (image = (short *)malloc(size)))
  124.         return (struct pixrect *)NULL;
  125.  
  126.     /*
  127.      * Set up the pr.
  128.      */
  129.     mpr->mpr_pr.pr_ops = &mem_ops;
  130.     mpr->mpr_pr.pr_width = w;
  131.     mpr->mpr_pr.pr_height = h;
  132.     mpr->mpr_pr.pr_depth = d;
  133.     mpr->mpr_pr.pr_data = (caddr_t)&mpr->mpr_data;
  134.  
  135.     /*
  136.      * Set up the mpr_data
  137.      */
  138.     mpr->mpr_data.md_linebytes = linebytes;
  139.     mpr->mpr_data.md_image = image;
  140.     mpr->mpr_data.md_offset.x = 0;
  141.     mpr->mpr_data.md_offset.y = 0;
  142.     mpr->mpr_data.md_primary = TRUE;
  143.     mpr->mpr_data.md_flags = 0;
  144.  
  145.     /*
  146.      * Return the pr.
  147.      */
  148.     return &mpr->mpr_pr;
  149. }
  150.  
  151. /*
  152.  * pr_free:
  153.  *    Free the memory associated with a pixrect.
  154.  *    Returns a pointer to no pixrect structure.
  155.  */
  156.  
  157. struct pixrect *
  158. pr_free(mpr)
  159. struct mem_pixrect *mpr;
  160. {
  161.     short *image;
  162.  
  163.     if((image = mpr->mpr_data.md_image))
  164.     {
  165.         if(mpr->mpr_data.md_primary)
  166.             free(image);
  167.         mpr->mpr_data.md_image = (short *)NULL;
  168.     }
  169.     mpr->mpr_pr.pr_width = 0;
  170.     mpr->mpr_pr.pr_height = 0;
  171.  
  172.     return (struct pixrect *)NULL;
  173. }
  174.  
  175. /*
  176.  * pr_check:
  177.  *    Check that a designated pixrect has memory allocated for an image
  178.  *    of size w, h, d. If not, free any existing memory and allocate
  179.  *    more memory. This is equivalent to, but much faster than, a
  180.  *    sequence of
  181.  *        pr_destroy(mpr);
  182.  *        mpr = mem_create(w, h, d);
  183.  */
  184.  
  185. struct pixrect *
  186. pr_check(mpr, w, h, d)
  187. struct mem_pixrect *mpr;
  188. int w, h, d;
  189. {
  190.     /*
  191.      * If there is an image, check that it is the correct size.
  192.      */
  193.     if(mpr->mpr_data.md_image)
  194.     {
  195.         if(mpr->mpr_pr.pr_width == w &&
  196.           mpr->mpr_pr.pr_height == h &&
  197.           mpr->mpr_pr.pr_depth == d)
  198.             return &mpr->mpr_pr;
  199.  
  200.         (void)pr_free(mpr);
  201.     }
  202.  
  203.     return pr_alloc(mpr, w, h, d);
  204. }
  205.  
  206. /*
  207.  * pr_link:
  208.  *    Link the memory of mpr1 to mpr2, making mpr2 a secondary pixrect.
  209.  */
  210.  
  211. struct pixrect *
  212. pr_link(mpr1, mpr2)
  213. struct mem_pixrect *mpr1;
  214. struct mem_pixrect *mpr2;
  215. {
  216.     /*
  217.      * Free the existing memory, if any.
  218.      */
  219.     (void)pr_free(mpr2);
  220.  
  221.     /*
  222.      * Set up the pr.
  223.      */
  224.     mpr2->mpr_pr.pr_ops = &mem_ops;
  225.     mpr2->mpr_pr.pr_width = mpr1->mpr_pr.pr_width;
  226.     mpr2->mpr_pr.pr_height = mpr1->mpr_pr.pr_height;
  227.     mpr2->mpr_pr.pr_depth = mpr1->mpr_pr.pr_depth;
  228.     mpr2->mpr_pr.pr_data = (caddr_t)&mpr2->mpr_data;
  229.  
  230.     /*
  231.      * Set up the mpr_data
  232.      */
  233.     mpr2->mpr_data.md_linebytes = mpr1->mpr_data.md_linebytes;
  234.     mpr2->mpr_data.md_image = mpr1->mpr_data.md_image;
  235.     mpr2->mpr_data.md_offset.x = mpr1->mpr_data.md_offset.x;
  236.     mpr2->mpr_data.md_offset.y = mpr1->mpr_data.md_offset.y;
  237.     mpr2->mpr_data.md_primary = FALSE;
  238.     mpr2->mpr_data.md_flags = 0;
  239.  
  240.     /*
  241.      * Return the pr.
  242.      */
  243.     return &mpr2->mpr_pr;
  244. }
  245.  
  246. /*
  247.  * Colour Map Stuff
  248.  * ================
  249.  */
  250.  
  251. #define M4F    0
  252. #define M4T    (M4F+16)
  253. #define M3F    (M4T+1)
  254. #define M3T    (M3F+24)
  255. #define M2F    (M3T+1)
  256. #define M2T    (M2F+4)
  257.  
  258. uchar    cmap_red[64] =
  259. {
  260. #ifdef NEVER
  261.     /* Cmap with GAMMA=2,2,2,20,20,20 */
  262.     /* 4x4 from 0 to 16 */
  263.     255, 247, 239, 231, 223, 214, 205, 196, 186,
  264.     175, 163, 151, 137, 121, 103, 78, 20,
  265.  
  266.     /* 3x3 from 17 to 41 */
  267.     255, 250, 244, 239, 234, 229, 223, 217, 211,
  268.     205, 199, 192, 186, 179, 171, 163, 155,
  269.     146, 137, 127, 115, 103, 87, 67, 20,
  270.  
  271.     /* 2x2 from 42 to 46 */
  272.     255, 223, 186, 137, 20,
  273.  
  274.     /* spare */
  275.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  276. #endif NEVER
  277.     /* Cmap with GAMMA=1.3,1.3,1.3,0,0,0 */
  278.     /* 4x4 from 0 to 16 */
  279.     255, 242, 230, 217, 204, 191, 177, 163, 149,
  280.     135, 119, 104,  87,  70,  51,  30,   0,
  281.  
  282.     /* 3x3 from 17 to 41 */
  283.     255, 246, 238, 230, 221, 213, 204, 195, 186,
  284.     177, 168, 159, 149, 139, 130, 119, 109,
  285.      98,  87,  76,  64,  51,  37,  22,   0,
  286.  
  287.     /* 2x2 from 42 to 46 */
  288.     255, 204, 149,  87,   0,
  289.  
  290.     /* spare */
  291.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  292. };
  293.  
  294. uchar    cmap_green[64] =
  295. {
  296.     /* 4x4 from 0 to 16 */
  297.     255, 242, 230, 217, 204, 191, 177, 163, 149,
  298.     135, 119, 104,  87,  70,  51,  30,   0,
  299.  
  300.     /* 3x3 from 17 to 41 */
  301.     255, 246, 238, 230, 221, 213, 204, 195, 186,
  302.     177, 168, 159, 149, 139, 130, 119, 109,
  303.      98,  87,  76,  64,  51,  37,  22,   0,
  304.  
  305.     /* 2x2 from 42 to 46 */
  306.     255, 204, 149,  87,   0,
  307.  
  308.     /* spare */
  309.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  310. };
  311.  
  312. uchar    cmap_blue[64] =
  313. {
  314.     /* 4x4 from 0 to 16 */
  315.     255, 242, 230, 217, 204, 191, 177, 163, 149,
  316.     135, 119, 104,  87,  70,  51,  30,   0,
  317.  
  318.     /* 3x3 from 17 to 41 */
  319.     255, 246, 238, 230, 221, 213, 204, 195, 186,
  320.     177, 168, 159, 149, 139, 130, 119, 109,
  321.      98,  87,  76,  64,  51,  37,  22,   0,
  322.  
  323.     /* 2x2 from 42 to 46 */
  324.     255, 204, 149,  87,   0,
  325.  
  326.     /* spare */
  327.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  328. };
  329.  
  330. double            gamma_red = 2.0;
  331. double            gamma_green = 2.0;
  332. double            gamma_blue = 2.0;
  333. int            min_red = 20;
  334. int            min_green = 20;
  335. int            min_blue = 20;
  336.  
  337. forward void        make_one_cmap();
  338.  
  339. void
  340. make_cmap()
  341. {
  342.     char *e;
  343.  
  344.     if((e = getenv("DVIPAGE_GAMMA")) == NULL)
  345.         return;
  346.  
  347.     min_red = 20;
  348.     min_green = 20;
  349.     min_blue = 20;
  350.     gamma_red = 0.0;
  351.     gamma_green = 0.0;
  352.     gamma_blue = 0.0;
  353.  
  354.     (void)sscanf(e, " %lf,%lf,%lf,%d,%d,%d ",
  355.       &gamma_red, &gamma_green, &gamma_blue,
  356.       &min_red, &min_green, &min_blue);
  357.  
  358.     if(gamma_red == 0.0)
  359.         gamma_red = 1.3;
  360.     if(gamma_green == 0.0)
  361.         gamma_green = gamma_red;
  362.     if(gamma_blue == 0.0)
  363.         gamma_blue = gamma_red;
  364.  
  365.     make_one_cmap(cmap_red, 1.0/gamma_red, min_red);
  366.     make_one_cmap(cmap_green, 1.0/gamma_green, min_green);
  367.     make_one_cmap(cmap_blue, 1.0/gamma_blue, min_blue);
  368. }
  369.  
  370. void
  371. make_one_cmap(cmap, power, mn)
  372. uchar cmap[];
  373. double power;
  374. int mn;
  375. {
  376.     int i;
  377.  
  378.     /*
  379.      * 4x4 cmap.
  380.      */
  381.     for(i = M4F; i <= M4T; i++)
  382.         cmap[i] = (uchar)(pow((double)(M4T - i) / (M4T - M4F), power)
  383.           * (255 - mn) + mn);
  384.  
  385.     /*
  386.      * 3x3 cmap.
  387.      */
  388.     for(i = M3F; i <= M3T; i++)
  389.         cmap[i] = (uchar)(pow((double)(M3T - i) / (M3T - M3F), power)
  390.           * (255 - mn) + mn);
  391.  
  392.     /*
  393.      * 2x2 cmap.
  394.      */
  395.     for(i = M2F; i <= M2T; i++)
  396.         cmap[i] = (uchar)(pow((double)(M2T - i) / (M2T - M2F), power)
  397.           * (255 - mn) + mn);
  398.  
  399.     cmap[63] = mn;
  400. }
  401.  
  402. /*
  403.  * Tally table used to compute the number of bits in packed words.
  404.  * This is used in computing the number of bits in a 4x4 region of
  405.  * a packed image.
  406.  *
  407.  * The packed word is used as an index into this table;
  408.  * The most significant 16 bits of the value obtained represent the
  409.  * number of bits in the upper half of the index, with each bit counted
  410.  * with a weight of 15.
  411.  * The least significant 16 bits of the value obtained represent the
  412.  * number of bits in the l;ower hald of the index, with each bit counted
  413.  * with a weight of 15.
  414.  *
  415.  * By combining the upper and lower halves in a single word, the values
  416.  * for the four vertically adjacent words can be combined with each other
  417.  * in a single addition per word, adding simultaneously both the tallies
  418.  * for the left and the right halves of the word.
  419.  */
  420.  
  421. static int tally4[] =
  422. {
  423.     0x00000000, 0x00000001, 0x00000001, 0x00000002,
  424.     0x00000001, 0x00000002, 0x00000002, 0x00000003,
  425.     0x00000001, 0x00000002, 0x00000002, 0x00000003,
  426.     0x00000002, 0x00000003, 0x00000003, 0x00000004,
  427.     0x00010000, 0x00010001, 0x00010001, 0x00010002,
  428.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  429.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  430.     0x00010002, 0x00010003, 0x00010003, 0x00010004,
  431.     0x00010000, 0x00010001, 0x00010001, 0x00010002,
  432.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  433.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  434.     0x00010002, 0x00010003, 0x00010003, 0x00010004,
  435.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  436.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  437.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  438.     0x00020002, 0x00020003, 0x00020003, 0x00020004,
  439.     0x00010000, 0x00010001, 0x00010001, 0x00010002,
  440.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  441.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  442.     0x00010002, 0x00010003, 0x00010003, 0x00010004,
  443.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  444.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  445.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  446.     0x00020002, 0x00020003, 0x00020003, 0x00020004,
  447.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  448.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  449.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  450.     0x00020002, 0x00020003, 0x00020003, 0x00020004,
  451.     0x00030000, 0x00030001, 0x00030001, 0x00030002,
  452.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  453.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  454.     0x00030002, 0x00030003, 0x00030003, 0x00030004,
  455.     0x00010000, 0x00010001, 0x00010001, 0x00010002,
  456.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  457.     0x00010001, 0x00010002, 0x00010002, 0x00010003,
  458.     0x00010002, 0x00010003, 0x00010003, 0x00010004,
  459.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  460.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  461.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  462.     0x00020002, 0x00020003, 0x00020003, 0x00020004,
  463.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  464.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  465.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  466.     0x00020002, 0x00020003, 0x00020003, 0x00020004,
  467.     0x00030000, 0x00030001, 0x00030001, 0x00030002,
  468.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  469.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  470.     0x00030002, 0x00030003, 0x00030003, 0x00030004,
  471.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  472.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  473.     0x00020001, 0x00020002, 0x00020002, 0x00020003,
  474.     0x00020002, 0x00020003, 0x00020003, 0x00020004,
  475.     0x00030000, 0x00030001, 0x00030001, 0x00030002,
  476.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  477.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  478.     0x00030002, 0x00030003, 0x00030003, 0x00030004,
  479.     0x00030000, 0x00030001, 0x00030001, 0x00030002,
  480.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  481.     0x00030001, 0x00030002, 0x00030002, 0x00030003,
  482.     0x00030002, 0x00030003, 0x00030003, 0x00030004,
  483.     0x00040000, 0x00040001, 0x00040001, 0x00040002,
  484.     0x00040001, 0x00040002, 0x00040002, 0x00040003,
  485.     0x00040001, 0x00040002, 0x00040002, 0x00040003,
  486.     0x00040002, 0x00040003, 0x00040003, 0x00040004,
  487. };
  488.  
  489. /*
  490.  * Tally table used to compute the number of bits in packed words.
  491.  * This is used in computing the number of bits in a 3x3 region of
  492.  * a packed image.
  493.  *
  494.  * The packed word is used as an index into this table;
  495.  * Bits 23..16 of the value obtained represent the number of bits in
  496.  * the upper 2.67 bits of the index, with each bit counted with a weight
  497.  * of 15. etc. etc.
  498.  *
  499.  * By combining the three parts in a single word, the values
  500.  * for the three vertically adjacent words can be combined with each other
  501.  * in a single addition per word, adding simultaneously both the tallies
  502.  * for the left and the right halves of the word.
  503.  */
  504.  
  505. static int tally3[] =
  506. {
  507.     0x00000000, 0x00000003, 0x00000003, 0x00000006,
  508.     0x00000102, 0x00000105, 0x00000105, 0x00000108,
  509.     0x00000300, 0x00000303, 0x00000303, 0x00000306,
  510.     0x00000402, 0x00000405, 0x00000405, 0x00000408,
  511.     0x00000300, 0x00000303, 0x00000303, 0x00000306,
  512.     0x00000402, 0x00000405, 0x00000405, 0x00000408,
  513.     0x00000600, 0x00000603, 0x00000603, 0x00000606,
  514.     0x00000702, 0x00000705, 0x00000705, 0x00000708,
  515.     0x00020100, 0x00020103, 0x00020103, 0x00020106,
  516.     0x00020202, 0x00020205, 0x00020205, 0x00020208,
  517.     0x00020400, 0x00020403, 0x00020403, 0x00020406,
  518.     0x00020502, 0x00020505, 0x00020505, 0x00020508,
  519.     0x00020400, 0x00020403, 0x00020403, 0x00020406,
  520.     0x00020502, 0x00020505, 0x00020505, 0x00020508,
  521.     0x00020700, 0x00020703, 0x00020703, 0x00020706,
  522.     0x00020802, 0x00020805, 0x00020805, 0x00020808,
  523.     0x00030000, 0x00030003, 0x00030003, 0x00030006,
  524.     0x00030102, 0x00030105, 0x00030105, 0x00030108,
  525.     0x00030300, 0x00030303, 0x00030303, 0x00030306,
  526.     0x00030402, 0x00030405, 0x00030405, 0x00030408,
  527.     0x00030300, 0x00030303, 0x00030303, 0x00030306,
  528.     0x00030402, 0x00030405, 0x00030405, 0x00030408,
  529.     0x00030600, 0x00030603, 0x00030603, 0x00030606,
  530.     0x00030702, 0x00030705, 0x00030705, 0x00030708,
  531.     0x00050100, 0x00050103, 0x00050103, 0x00050106,
  532.     0x00050202, 0x00050205, 0x00050205, 0x00050208,
  533.     0x00050400, 0x00050403, 0x00050403, 0x00050406,
  534.     0x00050502, 0x00050505, 0x00050505, 0x00050508,
  535.     0x00050400, 0x00050403, 0x00050403, 0x00050406,
  536.     0x00050502, 0x00050505, 0x00050505, 0x00050508,
  537.     0x00050700, 0x00050703, 0x00050703, 0x00050706,
  538.     0x00050802, 0x00050805, 0x00050805, 0x00050808,
  539.     0x00030000, 0x00030003, 0x00030003, 0x00030006,
  540.     0x00030102, 0x00030105, 0x00030105, 0x00030108,
  541.     0x00030300, 0x00030303, 0x00030303, 0x00030306,
  542.     0x00030402, 0x00030405, 0x00030405, 0x00030408,
  543.     0x00030300, 0x00030303, 0x00030303, 0x00030306,
  544.     0x00030402, 0x00030405, 0x00030405, 0x00030408,
  545.     0x00030600, 0x00030603, 0x00030603, 0x00030606,
  546.     0x00030702, 0x00030705, 0x00030705, 0x00030708,
  547.     0x00050100, 0x00050103, 0x00050103, 0x00050106,
  548.     0x00050202, 0x00050205, 0x00050205, 0x00050208,
  549.     0x00050400, 0x00050403, 0x00050403, 0x00050406,
  550.     0x00050502, 0x00050505, 0x00050505, 0x00050508,
  551.     0x00050400, 0x00050403, 0x00050403, 0x00050406,
  552.     0x00050502, 0x00050505, 0x00050505, 0x00050508,
  553.     0x00050700, 0x00050703, 0x00050703, 0x00050706,
  554.     0x00050802, 0x00050805, 0x00050805, 0x00050808,
  555.     0x00060000, 0x00060003, 0x00060003, 0x00060006,
  556.     0x00060102, 0x00060105, 0x00060105, 0x00060108,
  557.     0x00060300, 0x00060303, 0x00060303, 0x00060306,
  558.     0x00060402, 0x00060405, 0x00060405, 0x00060408,
  559.     0x00060300, 0x00060303, 0x00060303, 0x00060306,
  560.     0x00060402, 0x00060405, 0x00060405, 0x00060408,
  561.     0x00060600, 0x00060603, 0x00060603, 0x00060606,
  562.     0x00060702, 0x00060705, 0x00060705, 0x00060708,
  563.     0x00080100, 0x00080103, 0x00080103, 0x00080106,
  564.     0x00080202, 0x00080205, 0x00080205, 0x00080208,
  565.     0x00080400, 0x00080403, 0x00080403, 0x00080406,
  566.     0x00080502, 0x00080505, 0x00080505, 0x00080508,
  567.     0x00080400, 0x00080403, 0x00080403, 0x00080406,
  568.     0x00080502, 0x00080505, 0x00080505, 0x00080508,
  569.     0x00080700, 0x00080703, 0x00080703, 0x00080706,
  570.     0x00080802, 0x00080805, 0x00080805, 0x00080808,
  571. };
  572.  
  573. /*
  574.  * Tally table used to compute the number of bits in packed words.
  575.  * This is used in computing the number of bits in a 2x2 region of
  576.  * a packed image.
  577.  *
  578.  * The packed word is used as an index into this table;
  579.  * The most significant 8 bits of the value obtained represent the
  580.  * number of bits in the upper half of the index, with each bit counted
  581.  * with a weight of 15.
  582.  * ...
  583.  * The least significant 8 bits of the value obtained represent the
  584.  * number of bits in the l;ower hald of the index, with each bit counted
  585.  * with a weight of 15.
  586.  *
  587.  * By combining the four pairs of tallies in a single word, the values
  588.  * for the two vertically adjacent words can be combined with each other
  589.  * in a single addition per word, adding simultaneously all four tallies
  590.  * for the four pairs of the word.
  591.  */
  592.  
  593. static int tally2[] =
  594. {
  595.     0x00000000, 0x00000001, 0x00000001, 0x00000002,
  596.     0x00000100, 0x00000101, 0x00000101, 0x00000102,
  597.     0x00000100, 0x00000101, 0x00000101, 0x00000102,
  598.     0x00000200, 0x00000201, 0x00000201, 0x00000202,
  599.     0x00010000, 0x00010001, 0x00010001, 0x00010002,
  600.     0x00010100, 0x00010101, 0x00010101, 0x00010102,
  601.     0x00010100, 0x00010101, 0x00010101, 0x00010102,
  602.     0x00010200, 0x00010201, 0x00010201, 0x00010202,
  603.     0x00010000, 0x00010001, 0x00010001, 0x00010002,
  604.     0x00010100, 0x00010101, 0x00010101, 0x00010102,
  605.     0x00010100, 0x00010101, 0x00010101, 0x00010102,
  606.     0x00010200, 0x00010201, 0x00010201, 0x00010202,
  607.     0x00020000, 0x00020001, 0x00020001, 0x00020002,
  608.     0x00020100, 0x00020101, 0x00020101, 0x00020102,
  609.     0x00020100, 0x00020101, 0x00020101, 0x00020102,
  610.     0x00020200, 0x00020201, 0x00020201, 0x00020202,
  611.     0x01000000, 0x01000001, 0x01000001, 0x01000002,
  612.     0x01000100, 0x01000101, 0x01000101, 0x01000102,
  613.     0x01000100, 0x01000101, 0x01000101, 0x01000102,
  614.     0x01000200, 0x01000201, 0x01000201, 0x01000202,
  615.     0x01010000, 0x01010001, 0x01010001, 0x01010002,
  616.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  617.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  618.     0x01010200, 0x01010201, 0x01010201, 0x01010202,
  619.     0x01010000, 0x01010001, 0x01010001, 0x01010002,
  620.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  621.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  622.     0x01010200, 0x01010201, 0x01010201, 0x01010202,
  623.     0x01020000, 0x01020001, 0x01020001, 0x01020002,
  624.     0x01020100, 0x01020101, 0x01020101, 0x01020102,
  625.     0x01020100, 0x01020101, 0x01020101, 0x01020102,
  626.     0x01020200, 0x01020201, 0x01020201, 0x01020202,
  627.     0x01000000, 0x01000001, 0x01000001, 0x01000002,
  628.     0x01000100, 0x01000101, 0x01000101, 0x01000102,
  629.     0x01000100, 0x01000101, 0x01000101, 0x01000102,
  630.     0x01000200, 0x01000201, 0x01000201, 0x01000202,
  631.     0x01010000, 0x01010001, 0x01010001, 0x01010002,
  632.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  633.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  634.     0x01010200, 0x01010201, 0x01010201, 0x01010202,
  635.     0x01010000, 0x01010001, 0x01010001, 0x01010002,
  636.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  637.     0x01010100, 0x01010101, 0x01010101, 0x01010102,
  638.     0x01010200, 0x01010201, 0x01010201, 0x01010202,
  639.     0x01020000, 0x01020001, 0x01020001, 0x01020002,
  640.     0x01020100, 0x01020101, 0x01020101, 0x01020102,
  641.     0x01020100, 0x01020101, 0x01020101, 0x01020102,
  642.     0x01020200, 0x01020201, 0x01020201, 0x01020202,
  643.     0x02000000, 0x02000001, 0x02000001, 0x02000002,
  644.     0x02000100, 0x02000101, 0x02000101, 0x02000102,
  645.     0x02000100, 0x02000101, 0x02000101, 0x02000102,
  646.     0x02000200, 0x02000201, 0x02000201, 0x02000202,
  647.     0x02010000, 0x02010001, 0x02010001, 0x02010002,
  648.     0x02010100, 0x02010101, 0x02010101, 0x02010102,
  649.     0x02010100, 0x02010101, 0x02010101, 0x02010102,
  650.     0x02010200, 0x02010201, 0x02010201, 0x02010202,
  651.     0x02010000, 0x02010001, 0x02010001, 0x02010002,
  652.     0x02010100, 0x02010101, 0x02010101, 0x02010102,
  653.     0x02010100, 0x02010101, 0x02010101, 0x02010102,
  654.     0x02010200, 0x02010201, 0x02010201, 0x02010202,
  655.     0x02020000, 0x02020001, 0x02020001, 0x02020002,
  656.     0x02020100, 0x02020101, 0x02020101, 0x02020102,
  657.     0x02020100, 0x02020101, 0x02020101, 0x02020102,
  658.     0x02020200, 0x02020201, 0x02020201, 0x02020202,
  659. };
  660.  
  661. /*
  662.  * P_row:
  663.  *    Access macro for obtaining a pointer to the bytes of a pixrect
  664.  *    starting at row `row'.
  665.  */
  666.  
  667. #define P_row(mpr, row) \
  668.     (uchar *)((int)((mpr)->mpr_data.md_image) + \
  669.       (int)((short)(row) * (short)((mpr)->mpr_data.md_linebytes)));
  670.  
  671. /*
  672.  * pr_sample_4:
  673.  *    Filter and sample mpr1 on a 4x4 basis into mpr2.
  674.  */
  675.  
  676. struct pixrect *
  677. pr_sample_4(mpr1, mpr2)
  678. struct mem_pixrect *mpr1;
  679. struct mem_pixrect *mpr2;
  680. {
  681.     int cols, rows;
  682.     int j;
  683.     register uchar *p0;        /* a5 */
  684.     register uchar *p1;        /* a4 */
  685.     register uchar *p2;        /* a3 */
  686.     register uchar *p3;        /* a2 */
  687.     register uchar *pr;
  688.     register uchar *er;
  689.     register int tallies;        /* d7 */
  690.     int line_offset;
  691.  
  692.     cols = mpr1->mpr_pr.pr_width / 4;
  693.     rows = mpr1->mpr_pr.pr_height / 4;
  694.  
  695.     if(verbose & DEBUG_IMSIZE)
  696.         fprintf(stderr, "pr_sample_4: (%d x %d) -> (%d x %d)\n",
  697.           mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
  698.  
  699.     /*
  700.      * Allocate output image.
  701.      */
  702.     if(! pr_check(mpr2, cols, rows, 8))
  703.         return (struct pixrect *)NULL;
  704.  
  705.     /*
  706.      * Do the sampling.
  707.      */
  708.     line_offset = mpr1->mpr_data.md_linebytes;
  709.     for(j = 0; j < rows; j++)
  710.     {
  711.         p0 = P_row(mpr1, j*4);
  712.         p1 = p0 + line_offset;
  713.         p2 = p1 + line_offset;
  714.         p3 = p2 + line_offset;
  715.  
  716.         pr = P_row(mpr2, j);
  717.  
  718.         for(er = pr + cols; pr < er; )
  719.         {
  720.             /*
  721.              * Test for all zero.
  722.             if(*p0 == 0 && *p1 == 0 && *p2 == 0 && *p3 == 0)
  723.             {
  724.                 *pr++ = 0;
  725.  
  726.                 if(pr >= er)
  727.                     break;
  728.  
  729.                 *pr++ = 0;
  730.             }
  731.             else
  732.              */
  733.             {
  734.                 tallies =
  735.                   tally4[*p0] +
  736.                   tally4[*p1] +
  737.                   tally4[*p2] +
  738.                   tally4[*p3];
  739.  
  740.                 /*
  741.                  * High order 4 bits
  742.                  */
  743.                 *pr++ = (tallies >> 16) + M4F;
  744.  
  745.                 if(pr >= er)
  746.                     break;
  747.  
  748.                 /*
  749.                  * Low order 4 bits
  750.                  */
  751.                 *pr++ = tallies + M4F;
  752.             }
  753.             p0++;
  754.             p1++;
  755.             p2++;
  756.             p3++;
  757.         }
  758.     }
  759.  
  760.     return &mpr2->mpr_pr;
  761. }
  762.  
  763. /*
  764.  * pr_sample_34:
  765.  *    Filter and sample mpr1 on a 2.67x4 basis into mpr2.
  766.  *    Tally count uses M3 table, and gets up to 32 pixels (weighted at 1/3)
  767.  *      divides by two to index into the 0..16 M4 table.
  768.  */
  769.  
  770. struct pixrect *
  771. pr_sample_34(mpr1, mpr2)
  772. struct mem_pixrect *mpr1;
  773. struct mem_pixrect *mpr2;
  774. {
  775.     int cols, rows;
  776.     int j;
  777.     register uchar *p0;        /* a5 */
  778.     register uchar *p1;        /* a4 */
  779.     register uchar *p2;        /* a3 */
  780.     register uchar *p3;        /* a2 */
  781.     register uchar *pr;
  782.     register uchar *er;
  783.     register int tallies;        /* d7 */
  784.     int line_offset;
  785.  
  786.     cols = mpr1->mpr_pr.pr_width * 3 / 8;
  787.     rows = mpr1->mpr_pr.pr_height / 4;
  788.  
  789.     if(verbose & DEBUG_IMSIZE)
  790.         fprintf(stderr, "pr_sample_34: (%d x %d) -> (%d x %d)\n",
  791.           mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
  792.  
  793.     /*
  794.      * Allocate output image.
  795.      */
  796.     if(! pr_check(mpr2, cols, rows, 8))
  797.         return (struct pixrect *)NULL;
  798.  
  799.     /*
  800.      * Do the sampling.
  801.      */
  802.     line_offset = mpr1->mpr_data.md_linebytes;
  803.     for(j = 0; j < rows; j++)
  804.     {
  805.         p0 = P_row(mpr1, j*4);
  806.         p1 = p0 + line_offset;
  807.         p2 = p1 + line_offset;
  808.         p3 = p2 + line_offset;
  809.  
  810.         pr = P_row(mpr2, j);
  811.  
  812.         for(er = pr + cols; pr < er; )
  813.         {
  814.             /*
  815.              * Test for all zero.
  816.             if(*p0 == 0 && *p1 == 0 && *p2 == 0)
  817.             {
  818.                 *pr++ = 0;
  819.  
  820.                 if(pr >= er)
  821.                     break;
  822.  
  823.                 *pr++ = 0;
  824.  
  825.                 if(pr >= er)
  826.                     break;
  827.  
  828.                 *pr++ = 0;
  829.             }
  830.             else
  831.              */
  832.             {
  833.                 tallies =
  834.                   tally3[*p0] +
  835.                   tally3[*p1] +
  836.                   tally3[*p2] +
  837.                   tally3[*p3];
  838.  
  839.                 /*
  840.                  * High order 3 bits
  841.                  */
  842.                 *pr++ = (tallies >> (16+1)) + M4F;
  843.  
  844.                 if(pr >= er)
  845.                     break;
  846.  
  847.                 *pr++ = (tallies >> (8+1)) + M4F;
  848.  
  849.                 if(pr >= er)
  850.                     break;
  851.  
  852.                 /*
  853.                  * Low order 3 bits
  854.                  */
  855.                 *pr++ = (tallies >> 1) + M4F;
  856.             }
  857.             p0++;
  858.             p1++;
  859.             p2++;
  860.             p3++;
  861.         }
  862.     }
  863.  
  864.     return &mpr2->mpr_pr;
  865. }
  866.  
  867. /*
  868.  * pr_sample_3:
  869.  *    Filter and sample mpr1 on a 3x3 basis into mpr2.
  870.  *    Note that the horizontal sampling is actually 3/8 rather than 1/3.
  871.  */
  872.  
  873. struct pixrect *
  874. pr_sample_3(mpr1, mpr2)
  875. struct mem_pixrect *mpr1;
  876. struct mem_pixrect *mpr2;
  877. {
  878.     int cols, rows;
  879.     int j;
  880.     register uchar *p0;        /* a5 */
  881.     register uchar *p1;        /* a4 */
  882.     register uchar *p2;        /* a3 */
  883.     register uchar *pr;        /* a2 */
  884.     register uchar *er;
  885.     register int tallies;        /* d7 */
  886.     int line_offset;
  887.  
  888.     cols = mpr1->mpr_pr.pr_width * 3 / 8;
  889.     rows = mpr1->mpr_pr.pr_height / 3;
  890.  
  891.     if(verbose & DEBUG_IMSIZE)
  892.         fprintf(stderr, "pr_sample_3: (%d x %d) -> (%d x %d)\n",
  893.           mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
  894.  
  895.     /*
  896.      * Allocate output image.
  897.      */
  898.     if(! pr_check(mpr2, cols, rows, 8))
  899.         return (struct pixrect *)NULL;
  900.  
  901.     /*
  902.      * Do the sampling.
  903.      */
  904.     line_offset = mpr1->mpr_data.md_linebytes;
  905.     for(j = 0; j < rows; j++)
  906.     {
  907.         p0 = P_row(mpr1, j*3);
  908.         p1 = p0 + line_offset;
  909.         p2 = p1 + line_offset;
  910.  
  911.         pr = P_row(mpr2, j);
  912.  
  913.         for(er = pr + cols; pr < er; )
  914.         {
  915.             /*
  916.              * Test for all zero.
  917.             if(*p0 == 0 && *p1 == 0 && *p2 == 0)
  918.             {
  919.                 *pr++ = 0;
  920.  
  921.                 if(pr >= er)
  922.                     break;
  923.  
  924.                 *pr++ = 0;
  925.  
  926.                 if(pr >= er)
  927.                     break;
  928.  
  929.                 *pr++ = 0;
  930.             }
  931.             else
  932.              */
  933.             {
  934.                 tallies =
  935.                   tally3[*p0] +
  936.                   tally3[*p1] +
  937.                   tally3[*p2];
  938.  
  939.                 /*
  940.                  * High order 3 bits
  941.                  */
  942.                 *pr++ = (tallies >> 16) + M3F;
  943.  
  944.                 if(pr >= er)
  945.                     break;
  946.  
  947.                 *pr++ = (tallies >> 8) + M3F;
  948.  
  949.                 if(pr >= er)
  950.                     break;
  951.  
  952.                 /*
  953.                  * Low order 3 bits
  954.                  */
  955.                 *pr++ = tallies + M3F;
  956.             }
  957.             p0++;
  958.             p1++;
  959.             p2++;
  960.         }
  961.     }
  962.  
  963.     return &mpr2->mpr_pr;
  964. }
  965.  
  966. /*
  967.  * pr_sample_2:
  968.  *    Filter and sample mpr1 on a 2x2 basis into mpr2.
  969.  */
  970.  
  971. struct pixrect *
  972. pr_sample_2(mpr1, mpr2)
  973. struct mem_pixrect *mpr1;
  974. struct mem_pixrect *mpr2;
  975. {
  976.     int cols, rows;
  977.     int j;
  978.     register uchar *p0;        /* a5 */
  979.     register uchar *p1;        /* a4 */
  980.     register uchar *pr;        /* a3 */
  981.     register uchar *er;        /* a2 */
  982.     register int tallies;        /* d7 */
  983.     int line_offset;
  984.  
  985.     cols = mpr1->mpr_pr.pr_width / 2;
  986.     rows = mpr1->mpr_pr.pr_height / 2;
  987.  
  988.     if(verbose & DEBUG_IMSIZE)
  989.         fprintf(stderr, "pr_sample_2: (%d x %d) -> (%d x %d)\n",
  990.           mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
  991.  
  992.     /*
  993.      * Allocate output image.
  994.      */
  995.     if(! pr_check(mpr2, cols, rows, 8))
  996.         return (struct pixrect *)NULL;
  997.  
  998.     /*
  999.      * Do the sampling.
  1000.      */
  1001.     line_offset = mpr1->mpr_data.md_linebytes;
  1002.     for(j = 0; j < rows; j++)
  1003.     {
  1004.         p0 = P_row(mpr1, j*2);
  1005.         p1 = p0 + line_offset;
  1006.  
  1007.         pr = P_row(mpr2, j);
  1008.  
  1009.         for(er = pr + cols; pr < er; )
  1010.         {
  1011.             /*
  1012.              * Test for all zero.
  1013.             if(*p0 == 0 && *p1 == 0)
  1014.             {
  1015.                 *pr++ = 0;
  1016.  
  1017.                 if(pr >= er)
  1018.                     break;
  1019.  
  1020.                 *pr++ = 0;
  1021.  
  1022.                 if(pr >= er)
  1023.                     break;
  1024.  
  1025.                 *pr++ = 0;
  1026.  
  1027.                 if(pr >= er)
  1028.                     break;
  1029.  
  1030.                 *pr++ = 0;
  1031.             }
  1032.             else
  1033.              */
  1034.             {
  1035.                 tallies =
  1036.                   tally2[*p0] +
  1037.                   tally2[*p1];
  1038.  
  1039.                 /*
  1040.                  * Highest two bits
  1041.                  */
  1042.                 *pr++ = (tallies >> 24) + M2F;
  1043.  
  1044.                 if(pr >= er)
  1045.                     break;
  1046.  
  1047.                 *pr++ = (tallies >> 16) + M2F;
  1048.  
  1049.                 if(pr >= er)
  1050.                     break;
  1051.  
  1052.                 *pr++ = (tallies >> 8) + M2F;
  1053.  
  1054.                 if(pr >= er)
  1055.                     break;
  1056.  
  1057.                 /*
  1058.                  * Lowest two bits
  1059.                  */
  1060.                 *pr++ = tallies + M2F;
  1061.             }
  1062.             p0++;
  1063.             p1++;
  1064.         }
  1065.     }
  1066.  
  1067.     return &mpr2->mpr_pr;
  1068. }
  1069.  
  1070. /*
  1071.  * pw_cover:
  1072.  *    Function which writes a pixrect onto a pixwin;
  1073.  *    where there are no src pixels, it writes background colour.
  1074.  */
  1075.  
  1076. void
  1077. pw_cover(dpw, dx, dy, dw, dh, op, spr, sx, sy)
  1078. Pixwin *dpw;
  1079. int dx, dy, dw, dh;
  1080. int op;
  1081. Pixrect *spr;
  1082. int sx, sy;
  1083. {
  1084.     int aw, ah;
  1085.  
  1086.     /*
  1087.      * Handle the left margin.
  1088.      * If the left margin is less than the width to be painted,
  1089.      * paint a margin, else paint the whole region and return.
  1090.      */
  1091.     if(sx < 0)
  1092.     {
  1093.         if(-sx < dw)
  1094.         {
  1095.             pw_writebackground(dpw, dx, dy, -sx, dh, op);
  1096.             dx -= sx;
  1097.             sx = 0;
  1098.             dw += sx;
  1099.         }
  1100.         else
  1101.         {
  1102.             pw_writebackground(dpw, dx, dy, dw, dh, op);
  1103.             return;
  1104.         }
  1105.     }
  1106.  
  1107.     /*
  1108.      * Handle the top margin.
  1109.      * If the top margin is less thatn the width to be painted,
  1110.      * paint a margin, else paint the whole region and return.
  1111.      */
  1112.     if(sy < 0)
  1113.     {
  1114.         if(-sy < dh)
  1115.         {
  1116.             pw_writebackground(dpw, dx, dy, dw, -sy, op);
  1117.             dy -= sy;
  1118.             sy = 0;
  1119.             dh += sy;
  1120.         }
  1121.         else
  1122.         {
  1123.             pw_writebackground(dpw, dx, dy, dw, dh, op);
  1124.             return;
  1125.         }
  1126.     }
  1127.  
  1128.     /*
  1129.      * Handle the right margin.
  1130.      * aw = available width of source image.
  1131.      * If available width > 0 paint a margin of dw-aw width,
  1132.      * otherwise paint the whole region.
  1133.      */
  1134.     aw = spr->pr_width-sx;
  1135.     if(dw > aw)
  1136.     {
  1137.         if(aw > 0)
  1138.         {
  1139.             pw_writebackground(dpw, dx+aw, dy, dw-aw, dh, op);
  1140.             dw = aw;
  1141.         }
  1142.         else
  1143.         {
  1144.             pw_writebackground(dpw, dx, dy, dw, dh, op);
  1145.             return;
  1146.         }
  1147.     }
  1148.  
  1149.     /*
  1150.      * Handle the bottom margin.
  1151.      * ah = available height of source image.
  1152.      * If available height > 0 paint a margin of dh-ah height,
  1153.      * otherwise paint the whole region.
  1154.      */
  1155.     ah = spr->pr_height-sy;
  1156.     if(dh > ah)
  1157.     {
  1158.         if(ah > 0)
  1159.         {
  1160.             pw_writebackground(dpw, dx, dy+ah, dw, dh-ah, op);
  1161.             dh = ah;
  1162.         }
  1163.         else
  1164.         {
  1165.             pw_writebackground(dpw, dx, dy, dw, dh, op);
  1166.             return;
  1167.         }
  1168.     }
  1169.  
  1170.     /*
  1171.      * Paint the image.
  1172.      */
  1173.     pw_write(dpw, dx, dy, dw, dh, op, spr, sx, sy);
  1174. }
  1175.  
  1176. /*
  1177.  * pr_rect:
  1178.  *    Draws a box with op and colour as specified.
  1179.  */
  1180.  
  1181. void
  1182. pr_rect(pr, x, y, w, h, t, op, value)
  1183. struct pixrect *pr;
  1184. int x, y, w, h;
  1185. int t;
  1186. int op, value;
  1187. {
  1188.     int i;
  1189.  
  1190.     for(i = 0; i < t; i++)
  1191.     {
  1192.         pr_vector(pr, x, y, x+w-1, y, op, value);
  1193.         pr_vector(pr, x+w-1, y+1, x+w-1, y+h-2, op, value);
  1194.         pr_vector(pr, x, y+h-1, x+w-1, y+h-1, op, value);
  1195.         pr_vector(pr, x, y+1, x, y+h-2, op, value);
  1196.  
  1197.         x += 1;
  1198.         y += 1;
  1199.         w -= 2;
  1200.         h -= 2;
  1201.  
  1202.         if(w <= 0 || h <= 0)
  1203.             break;
  1204.     }
  1205. }
  1206.  
  1207. /*
  1208.  * pw_rect:
  1209.  *    Draws a box with op and colour as specified.
  1210.  */
  1211.  
  1212. void
  1213. pw_rect(pw, x, y, w, h, t, op, value)
  1214. Pixwin *pw;
  1215. int x, y, w, h;
  1216. int t;
  1217. int op, value;
  1218. {
  1219.     int i;
  1220.     Rect r;
  1221.  
  1222.     r.r_left = x;
  1223.     r.r_top = y;
  1224.     r.r_width = w;
  1225.     r.r_height = h;
  1226.     pw_lock(pw, &r);
  1227.  
  1228.     for(i = 0; i < t; i++)
  1229.     {
  1230.         pw_vector(pw, x, y, x+w-1, y, op, value);
  1231.         pw_vector(pw, x+w-1, y+1, x+w-1, y+h-2, op, value);
  1232.         pw_vector(pw, x, y+h-1, x+w-1, y+h-1, op, value);
  1233.         pw_vector(pw, x, y+1, x, y+h-2, op, value);
  1234.  
  1235.         x += 1;
  1236.         y += 1;
  1237.         w -= 2;
  1238.         h -= 2;
  1239.  
  1240.         if(w <= 0 || h <= 0)
  1241.             break;
  1242.     }
  1243.  
  1244.     pw_unlock(pw);
  1245. }
  1246.